package ebpf

import (
	"bufio"
	"bytes"
	"io"
	"strings"

	"github.com/pkg/errors"

	"gitee.com/meilier/flower/util"
)

const (
	traceeEventTitle = "EVENT"
)

type tracee struct {
	content []byte
	syscall map[string]bool
}

func (t *tracee) Name() string {
	return "tracee"
}

func (t *tracee) Collect() error {
	traceeCommand := `docker run --name tracee --rm -it --pid=host --cgroupns=host --privileged-v /etc/os-release:/etc/os-release-host:ro   -e LIBBPFGO_OSRELEASE_FILE=/etc/os-release-host -e TRACEE_EBPF_ONLY=1 aquasec/tracee:latest --trace container=new`

	bytes, err := util.ExecCmdOutput(traceeCommand)
	if err != nil {
		return errors.Wrap(err, "collect failed with error")
	}

	t.content = bytes

	return nil
}

// TODO: add flag parser
func (t *tracee) Parser() error {
	if len(t.content) == 0 {
		return errors.Errorf("empty tracee content")
	}
	t.syscall = make(map[string]bool, 0)
	r := bufio.NewReader(bytes.NewReader(t.content))
	for {
		line, err := r.ReadString('\n')
		switch err {
		case io.EOF:
			call, err := getSyscall(line)
			if err != nil {
				return err
			}
			if _, ok := t.syscall[call]; !ok {
				t.syscall[call] = true
			}
			delete(t.syscall, traceeEventTitle)
			return nil
		case nil:
			call, err := getSyscall(line)
			if err != nil {
				return err
			}
			if _, ok := t.syscall[call]; !ok {
				t.syscall[call] = true
			}
		default:
			return errors.Wrap(err, "parse failed with error")
		}
	}
}

func getSyscall(line string) (string, error) {
	const syscallColumn = 6
	arr := strings.Fields(line)
	if len(arr) <= syscallColumn {
		return "", errors.Errorf("fields length is not enough")
	}
	return arr[syscallColumn], nil
}
